/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dspot.declex.actions;

import java.util.List;

import org.ohosannotations.annotations.RootContext;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.LayoutScatter;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.*;
import ohos.app.Context;
import ohos.agp.window.dialog.IDialog;

import com.dspot.declex.actions.runnable.DialogClickRunnable;
import com.dspot.declex.actions.runnable.DialogMultiChoiceClickRunnable;
import com.dspot.declex.annotation.RunWith;
import com.dspot.declex.annotation.action.ActionFor;
import com.dspot.declex.annotation.action.Assignable;
import com.dspot.declex.annotation.action.FormattedExpression;
import com.dspot.declex.annotation.action.StopOn;

/**
 * 警告对话框行动持有人
 *
 * @author Administrator
 * @since 2021-07-14
 */
@ActionFor("AlertDialog")
public class AlertDialogActionHolder {
    /**
     * 构建器
     */
    CommonDialog builder;

    /**
     * 积极的按钮文字
     */
    String positiveButtonText;
    /**
     * 积极的按钮res
     */
    int positiveButtonRes;

    /**
     * 负按钮文字
     */
    String negativeButtonText;
    /**
     * res -按钮
     */
    int negativeButtonRes;

    /**
     * 中性按钮文字
     */
    String neutralButtonText;
    /**
     * 中性按钮res
     */
    int neutralButtonRes;

    /**
     * 多的选择项
     */
    String[] multiChoiceItems;
    /**
     * 多选择物
     */
    int multiChoiceRes;

    /**
     * 检查项目
     */
    boolean[] checkedItems;

    /**
     * 项目
     */
    String[] items;
    /**
     * 物品res
     */
    int itemsRes;

    /**
     * 对话框
     */
    CommonDialog dialog;

    /**
     * 上下文
     */
    @RootContext
    Context context;

    /**
     * 自定义视图
     */
    private Component customView;

    /**
     * 初始化
     */
    void init() {
        builder = new CommonDialog(context);
    }

    //Here you can infer any parameter, the first parameter is the next listener

    /**
     * 构建
     *
     * @param PositiveButtonPressed <i><b>(default)</b></i> This Action Selector will be executed when the positive button is pressed in
     * the AlertDialog
     * @param NegativeButtonPressed This Action Selector will be executed when the negative button is pressed in
     * the AlertDialog
     * @param NeutralButtonPressed This Action Selector will be executed when the neutral button is pressed in
     * the AlertDialog
     * @param Canceled This Action Selector will be executed when the AlertDialog is canceled
     * @param ItemSelected 项目选择
     * @param MultiChoiceSelected 多选择选择
     * @param Dismissed 驳回了
     */
    void build(
        final DialogClickRunnable PositiveButtonPressed,
        final DialogClickRunnable NegativeButtonPressed,
        final DialogClickRunnable NeutralButtonPressed,
        final DialogClickRunnable ItemSelected,
        final DialogMultiChoiceClickRunnable MultiChoiceSelected,
        final Runnable Canceled,
        final Runnable Dismissed) {

        if (negativeButtonText != null) {
            builder.setButton(0,negativeButtonText, NegativeButtonPressed);
        } else if (negativeButtonRes != 0) {
            builder.setImageButton (0,negativeButtonRes, NegativeButtonPressed);
        }

        if (positiveButtonText != null) {
            builder.setButton(1,positiveButtonText, PositiveButtonPressed);
        } else if (positiveButtonRes != 0) {
            builder.setImageButton (1,positiveButtonRes, PositiveButtonPressed);
        }

        if (neutralButtonText != null) {
            builder.setButton(2,neutralButtonText, NeutralButtonPressed);
        } else if (neutralButtonRes != 0) {
            builder.setImageButton (2,neutralButtonRes, NeutralButtonPressed);
        }

//        if (items != null) {
//            builder.setItems(items, ItemSelected);
//        } else if (itemsRes != 0) {
//            builder.setItems(itemsRes, ItemSelected);
//        }
//
//        if (multiChoiceItems != null) {
//            builder.setMultiChoiceItems(multiChoiceItems, checkedItems, MultiChoiceSelected);
//        } else if (multiChoiceRes != 0) {
//            builder.setMultiChoiceItems(multiChoiceRes, checkedItems, MultiChoiceSelected);
//        }



        dialog = builder;

        if (Canceled != null) {
            dialog.setDestroyedListener(new CommonDialog.DestroyedListener() {
                @Override
                public void onDestroy() {
                    Canceled.run();
                }
            });
        }

        if (Dismissed != null || customView != null) {
            dialog.setDestroyedListener(new CommonDialog.DestroyedListener() {

                @Override
                public void onDestroy() {
                    if (customView != null) {
                        Component parent = (Component) customView.getComponentParent();
//                        parent.re(customView);
                    }
                    if (Dismissed != null) Dismissed.run();
                }

//                @Override
//                public void onDismiss(DialogInterface arg0) {
//                    if (customView != null) {
//                        ViewGroup parent = (ViewGroup) customView.getParent();
//                        parent.removeView(customView);
//                    }
//                    if (Dismissed != null) Dismissed.run();
//                }
            });
        }
        dialog.setDialogListener(new BaseDialog.DialogListener() {
            @Override
            public boolean isTouchOutside() {
                if (dialog != null) {
                    dialog.destroy();
                }
                return false;
            }
        });
    };

    /**
     * 执行
     */
    void execute() {
        if(dialog!=null) {
            dialog.show();
        }
    }

    /**
     * 对话框
     *
     * @return Internal Dialog instance.
     */
    @StopOn("show")
    public CommonDialog dialog() {
        return this.dialog;
    }

    /**
     * 对话框
     * Assigns the Internal Dialog instance.
     *
     * @param dialog The variable to which the dialog is going to be assigned
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder dialog(@Assignable("dialog") CommonDialog dialog) {
        return this;
    }

    /**
     * @return Builder layer to access the underlying Notifications Builder object
     *
     * @see support.v4.app.NotificationCompat.Builder Notifications Builder
     */
//    @StopOn("create")
//    public CommonDialog builder() {
//        return this.builder;
//    }

    /**
     * Set the title using the given resource id.
     *
     * @return This Builder object to allow for chaining of calls to set methods
     */
//    public AlertDialogActionHolder title(@StringRes int titleId) {
//        builder.setTitle(context.getString(titleId));
//        return this;
//    }

    /**
     * Set the title displayed in the {@link Dialog}.
     */
//    public AlertDialogActionHolder title(@FormattedExpression String title) {
//        builder.setTitle(title);
//        return this;
//    }

    /**
     * Set the title using the custom view {@code customTitleView}.
     * <p>
     * The methods {@link #setContentText(int)} and {@link #setIcon(int)} should
     * be sufficient for most titles, but this is provided if the title
     * needs more customization. Using this will replace the title and icon
     * set via the other methods.
     * <p>
     * <strong>Note:</strong> To ensure consistent styling, the custom view
     * should be inflated or constructed using the alert dialog's themed
     * context obtained via {@link #getContext()}.
     *
     * @param customTitleView the custom view to use as the title
     */
//    public AlertDialogActionHolder customTitle(@Nullable View customTitleView){
//        builder.setCustomTitle(customTitleView)   ;
//        return this;
//    }

    /**
     * Set the message to display using the given resource id.
     */
//    public AlertDialogActionHolder message(@StringRes int messageId) {
//        builder.setMessage(context.getString(messageId));
//        return this;
//    }

    /**
     * 消息
     * Set the message to display.
     *
     * @param message 消息
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder message(@FormattedExpression String message) {
//        builder.setMessage(message);
        builder.setContentText(message);
        return this;
    }

    /**
     * Set the resource id of the {@link Drawable} to be used in the title.
     * <p>
     * Takes precedence over values set using {@link #setIcon(Drawable)}.
     */
//    public AlertDialogActionHolder icon(@DrawableRes int iconId){
//        builder.setIcon(iconId);
//        return this;
//    }

    /**
     * Set the {@link Drawable} to be used in the title.
     * <p>
     * <strong>Note:</strong> To ensure consistent styling, the drawable
     * should be inflated or constructed using the alert dialog's themed
     * context obtained via {@link #getContext()}.
     */
//    public AlertDialogActionHolder icon(@Nullable Drawable icon){
//        builder.setIcon(icon);
//        return this;
//    }

    /**
     * Set an icon as supplied by a theme attribute. e.g.
     * {@link .R.attr#alertDialogIcon}.
     * <p>
     * Takes precedence over values set using {@link #setIcon(int)} or
     * {@link #setIcon(Drawable)}.
     *
     * @param attrId ID of a theme attribute that points to a drawable resource.
     */
//    public AlertDialogActionHolder setIconAttribute(@AttrRes int attrId){
//        builder.setIconAttribute(attrId);
//        return this;
//    }

    /**
     * 积极的按钮
     * Set a listener to be invoked when the positive button of the dialog is pressed.
     *
     * @param textId The resource id of the text to display in the positive button
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder positiveButton(int textId) {
        positiveButtonRes = textId;
        return this;
    }

    /**
     * 积极的按钮
     * Set a listener to be invoked when the positive button of the dialog is pressed.
     *
     * @param text The text to display in the positive button
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder positiveButton(@FormattedExpression String text) {
        positiveButtonText = text;
        return this;
    }

    /**
     * 消极的按钮
     * Set a listener to be invoked when the negative button of the dialog is pressed.
     *
     * @param textId The resource id of the text to display in the negative button
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder negativeButton(int textId) {
        negativeButtonRes = textId;
        return this;
    }

    /**
     * 消极的按钮
     * Set a listener to be invoked when the negative button of the dialog is pressed.
     *
     * @param text The text to display in the negative button
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder negativeButton(@FormattedExpression String text) {
        negativeButtonText = text;
        return this;
    }

    /**
     * 中性的按钮
     * Set a listener to be invoked when the neutral button of the dialog is pressed.
     *
     * @param textId The resource id of the text to display in the neutral button
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder neutralButton(int textId) {
        neutralButtonRes = textId;
        return this;
    }

    /**
     * 中性的按钮
     * Set a listener to be invoked when the negative button of the dialog is pressed.
     *
     * @param text The text to display in the negative button
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder neutralButton(@FormattedExpression String text) {
        neutralButtonText = text;
        return this;
    }

    /**
     * 可取消的
     * Sets whether the dialog is cancelable or not.  Default is true.
     *
     * @param cancelable 可取消的
     * @return {@link AlertDialogActionHolder}
     */
    public void cancelable(boolean cancelable){
        if(cancelable){
            builder.hide();
        }else{
            builder.destroy();
        }
//        return this;
    }

    /**
     * 项目
     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
     * selected item via the supplied listener. This should be an array type i.e. R.array.foo
     *
     * @param res res
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder items(int res) {
        this.itemsRes = res;
        return this;
    }

    /**
     * 项目
     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
     * selected item via the supplied listener.
     *
     * @param items 项目
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder items(String ... items) {
        this.items = items;
        return this;
    }

    /**
     * 项目
     * Set a list of items to be displayed in the dialog as the content, you will be notified of the
     * selected item via the supplied listener.
     *
     * @param items 项目
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder items(List<?> items) {
        this.items = new String[items.size()];
        for (int i = 0; i < items.size(); i++) {
            this.items[i] = items.get(i).toString();
        }
        return this;
    }

    /**
     * 多的选择
     * Set a list of items to be displayed in the dialog as the content,
     * you will be notified of the selected item via the supplied listener.
     * This should be an array type, e.g. R.array.foo. The list will have
     * a check mark displayed to the right of the text for each checked
     * item. Clicking on an item in the list will not dismiss the dialog.
     * Clicking on a button will dismiss the dialog.
     *
     * @param res the resource id of an array i.e. R.array.foo
     * @param checkedItemsArray specifies which items are checked. It should be null in which case no
     * items are checked. If non null it must be exactly the same length as the array of
     * items.
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder multiChoice(int res, boolean[] checkedItemsArray) {
        multiChoiceRes = res;
        checkedItems = checkedItemsArray;
        return this;
    }

    /**
     * 多的选择
     * Set a list of items to be displayed in the dialog as the content,
     * you will be notified of the selected item via the supplied listener.
     * This should be an array type, e.g. R.array.foo. The list will have
     * a check mark displayed to the right of the text for each checked
     * item. Clicking on an item in the list will not dismiss the dialog.
     * Clicking on a button will dismiss the dialog.
     *
     * @param res the resource id of an array i.e. R.array.foo
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder multiChoice(int res) {
        multiChoiceRes = res;
        return this;
    }

    /**
     * 多的选择
     * Set a list of items to be displayed in the dialog as the content,
     * you will be notified of the selected item via the supplied listener.
     * The list will have a check mark displayed to the right of the text
     * for each checked item. Clicking on an item in the list will not
     * dismiss the dialog. Clicking on a button will dismiss the dialog.
     *
     * @param items the text of the items to be displayed in the list.
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder multiChoice(String ... items) {
        multiChoiceItems = items;
        return this;
    }

    /**
     * 多的选择
     * Set a list of items to be displayed in the dialog as the content,
     * you will be notified of the selected item via the supplied listener.
     * The list will have a check mark displayed to the right of the text
     * for each checked item. Clicking on an item in the list will not
     * dismiss the dialog. Clicking on a button will dismiss the dialog.
     *
     * @param items the text of the items to be displayed in the list.
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder multiChoice(List<?> items) {
        this.multiChoiceItems = new String[items.size()];
        for (int i = 0; i < items.size(); i++) {
            this.multiChoiceItems[i] = items.get(i).toString();
        }
        return this;
    }

    /**
     * 多的选择
     * Set a list of items to be displayed in the dialog as the content,
     * you will be notified of the selected item via the supplied listener.
     * The list will have a check mark displayed to the right of the text
     * for each checked item. Clicking on an item in the list will not
     * dismiss the dialog. Clicking on a button will dismiss the dialog.
     *
     * @param items the text of the items to be displayed in the list.
     * @param checkedItemsArray specifies which items are checked. It should be null in which case no
     * items are checked. If non null it must be exactly the same length as the array of
     * items.
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder multiChoice(List<String> items, boolean[] checkedItemsArray) {
        multiChoiceItems = new String[items.size()];
        multiChoiceItems = items.toArray(multiChoiceItems);
        checkedItems = checkedItemsArray;
        return this;
    }

    /**
     * 视图
     * Set a custom view resource to be the contents of the Dialog. The
     * resource will be inflated, adding all top-level views to the screen.
     *
     * @param layoutResId View Resource ID to be inflated.
     * @return {@link AlertDialogActionHolder}
     */
    public AlertDialogActionHolder setView(int layoutResId) {
        Component component = LayoutScatter.getInstance(context).parse(layoutResId,null,false);
        builder.setContentCustomComponent(component);
        return this;
    }

    /**
     * Sets a custom view to be the contents of the alert dialog.
     */
    public AlertDialogActionHolder view(int width,int height) {
        builder.setSize(width,height);
        return this;
    }

}

